package com.yboot.starter.mybatis.core.base.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlInjectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yboot.starter.common.core.utils.ReflectUtils;
import com.yboot.starter.common.core.web.page.PageVO;
import com.yboot.starter.common.core.web.validation.InsertGroup;
import com.yboot.starter.common.core.web.validation.ValidationUtil;
import com.yboot.starter.mybatis.core.base.entity.BaseEntity;
import com.yboot.starter.mybatis.core.base.entity.BaseIdEntity;
import com.yboot.starter.mybatis.core.base.query.PageQuery;
import com.yboot.starter.mybatis.core.utils.MybatisPageUtil;
import com.yboot.starter.mybatis.core.utils.QueryWrapperHelper;
import com.yboot.starter.mybatis.core.validator.TableIndexValidatorApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.ValidationUtils;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.List;

/**
 * service层
 *
 * @param <L> 列表类型
 * @param <D> 详情类型
 * @param <Q> 查询条件类型
 * @param <C> 创建或修改请求参数类型
 * @author yangcs
 * @date 2025/8/15
 */
public abstract class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseIdEntity, L, D, Q extends PageQuery, C>
        extends ServiceImpl<M, T> implements IBaseService<T, L, D, Q, C> {
    //自定义数据方法
    protected final Type[] typeArguments = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments();
    protected final Class<L> listClass = this.currentListClass();
    protected final Class<D> detailClass = this.currentDetailClass();
    protected final Class<Q> queryClass = this.currentQueryClass();
    protected final List<Field> queryFields = ReflectUtils.getNonStaticFields(this.queryClass);

    @Autowired
    private TableIndexValidatorApi tableIndexValidatorApi;

    /**
     * 获取当前列表信息类型
     *
     * @return 当前列表信息类型
     */
    protected Class<L> currentListClass() {
        return (Class<L>)this.typeArguments[2];
    }

    /**
     * 获取当前详情信息类型
     *
     * @return 当前详情信息类型
     */
    protected Class<D> currentDetailClass() {
        return (Class<D>)this.typeArguments[3];
    }

    /**
     * 获取当前查询条件类型
     *
     * @return 当前查询条件类型
     */
    protected Class<Q> currentQueryClass() {
        return (Class<Q>)this.typeArguments[4];
    }
    @Override
    public PageVO<L> queryPage(Q query) {
        QueryWrapper<T> queryWrapper = this.buildQueryWrapper(query);
        IPage<T> iPage = baseMapper.selectPage(MybatisPageUtil.initPage(query), queryWrapper);
        List<L> list = BeanUtil.copyToList(iPage.getRecords(), listClass);
        list.forEach(this::fill);
        return MybatisPageUtil.ofPage(iPage, list);
    }

    @Override
    public List<L> list(Q query) {
        QueryWrapper<T> queryWrapper = this.buildQueryWrapper(query);
        List<T> result = this.list(queryWrapper);
        List<L> list = BeanUtil.copyToList(result, listClass);
        list.forEach(this::fill);
        return list;
    }

    @Override
    public D detail(Serializable id) {
        T result = this.getById(id);
        this.fill(result);
        return BeanUtil.copyProperties(result, detailClass);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String saveInfo(C r) {
        this.beforeCreate(r);
        T t = BeanUtil.copyProperties(r, super.getEntityClass());
        tableIndexValidatorApi.validateBeforeInsert(t, getEntityClass());
        save(t);
        this.afterCreate(r, t);
        return t.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateInfo(C r) {
        T t = BeanUtil.copyProperties(r, super.getEntityClass());
        tableIndexValidatorApi.validateBeforeUpdate(t, getEntityClass());
        String id = t.getId();
        Assert.notNull(id, "id is not null");
        this.beforeUpdate(r, id);
        baseMapper.updateById(t);
        this.afterUpdate(r, t);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(List<String> ids) {
        Assert.notEmpty(ids, "id is not null");
        this.beforeDelete(ids);
        List<T> list = baseMapper.selectByIds(ids);
        baseMapper.deleteByIds(ids);
        this.afterDelete(ids, list);
        return false;
    }

    /**
     * 新增前置处理
     *
     * @param req 创建信息
     */
    protected void beforeCreate(C req) {
        /* 新增前置处理 */
    }

    /**
     * 修改前置处理
     *
     * @param req 修改信息
     * @param id  ID
     */
    protected void beforeUpdate(C req, String id) {
        /* 修改前置处理 */
    }

    /**
     * 删除前置处理
     *
     * @param ids ID 列表
     */
    protected void beforeDelete(List<String> ids) {
        /* 删除前置处理 */
    }

    /**
     * 新增后置处理
     *
     * @param req    创建信息
     * @param entity 实体信息
     */
    protected void afterCreate(C req, T entity) {
        /* 新增后置处理 */
    }

    /**
     * 修改后置处理
     *
     * @param req    修改信息
     * @param entity 实体信息
     */
    protected void afterUpdate(C req, T entity) {
        /* 修改后置处理 */
    }

    /**
     * 删除后置处理
     *
     * @param ids ID 列表
     */
    protected void afterDelete(List<String> ids, List<T> list) {
        /* 删除后置处理 */
    }


    /**
     * 填充数据
     *
     * @param obj 待填充信息
     */
    protected void fill(Object obj) {
    }

    /**
     * 构建 QueryWrapper
     *
     * @param query 查询条件
     * @return QueryWrapper
     */
    protected QueryWrapper buildQueryWrapper(Q query) {
        QueryWrapper queryWrapper = new QueryWrapper();
        // 没有查询条件，直接返回
        if (query == null) {
            return queryWrapper;
        }
        // 解析并拼接查询条件
        return QueryWrapperHelper.build(query, queryFields, queryWrapper);
    }
}
